package com.ccx.demo.config;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Minio 文件服务
 * <pre>
 * https://docs.minio.io/
 * http://docs.minio.org.cn/
 * </pre>
 *
 * @author 谢长春 2020-11-13
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.app.files.type", havingValue = "minio")
@Slf4j
@Getter
@Setter
@ConfigurationProperties(prefix = "spring.app.files.minio")
public class MinioConfiguration {
    /**
     * 这里置空，文件存储在 bucketName
     */
    private String directory;
    /**
     * 文件服务访问地址
     */
    private String server;
    /**
     * 对象存储服务的URL
     */
    private String endpoint;
    /**
     * Access key就像用户ID，可以唯一标识你的账户。
     */
    private String accessKey;
    /**
     * Secret key是你账户的密码。
     */
    private String secretKey;
    /**
     * 区域
     */
    private String region;
    /**
     * 存储桶名称
     */
    private String bucketName;

    @Bean
    public CommandLineRunner printMinioConfigurationCommandLineRunner() {
        return args -> log.info(
                "\nspring.app.files.minio.directory【这里置空，文件存储在 bucketName】 : {}"
                        + "\nspring.app.files.minio.server【文件服务访问地址】 : {}"
                        + "\nspring.app.files.minio.endpoint【对象存储服务的URL】 : {}"
                        + "\nspring.app.files.minio.accessKey【Access key就像用户ID，可以唯一标识你的账户。】 : {}"
                        + "\nspring.app.files.minio.secretKey【Secret key是你账户的密码。】 : {}"
                        + "\nspring.app.files.minio.region【区域】 : {}"
                        + "\nspring.app.files.minio.bucketName【存储桶名称】 : {}"
                , directory
                , server
                , endpoint
                , accessKey
                , secretKey
                , region
                , bucketName
        );
    }

//    @Bean
//    @SneakyThrows
//    public MinioClient minioClient() {
//        final MinioClient minioClient = MinioClient.builder()
//                .endpoint(endpoint)
//                .credentials(accessKey, secretKey)
//                .build();
//        // 检查存储桶是否已经存在
//        final boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder()
//                .bucket(bucketName)
//                .build()
//        );
//        if (!isExist) {
//            // 创建存储桶
//            minioClient.makeBucket(MakeBucketArgs.builder()
//                    .bucket(bucketName)
//                    .build());
//            // 设置权限
//            // {"Statement": [{"Action": ["s3:GetBucketLocation", "s3:ListBucket"], "Effect": "Allow", "Principal": "*", "Resource": "arn:aws:s3:::%s"}, {"Action": "s3:GetObject", "Effect": "Allow", "Principal": "*", "Resource": "arn:aws:s3:::%s/myobject*"}], "Version": "2012-10-17"}
//            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
//                    .bucket(bucketName)
//                    .config(String.format("{\"Version\": \"2012-10-17\", \"Statement\": [{\"Action\": \"s3:GetObject\", \"Effect\": \"Allow\", \"Principal\": \"*\", \"Resource\": \"arn:aws:s3:::%s/*\"}]}"
//                            , bucketName
//                    ))
//                    .build());
//        }
//        log.info("minio 存储桶 【{}】 创建成功", bucketName);
//        return minioClient;
//    }

    /**
     * 这里不用 minio 官方客户端，替换成 AmazonS3 客户端。 官方客户端如果上传 图片或 html ，浏览器打开 url 时会变成下载，而不是直接预览
     *
     * @return {@link AmazonS3}
     */
    @Bean(destroyMethod = "shutdown")
    @SneakyThrows
    public AmazonS3 minioClient() {
        final ClientConfiguration clientConfiguration = new ClientConfiguration();
        clientConfiguration.setSignerOverride("AWSS3V4SignerType");

        final AmazonS3 s3Client = AmazonS3ClientBuilder
                .standard()
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region))
                .withPathStyleAccessEnabled(true)
                .withClientConfiguration(clientConfiguration)
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
                .build();
        // 检查存储桶是否已经存在
        final boolean isBucketExist = s3Client.doesBucketExistV2(bucketName);
        if (!isBucketExist) {
            // 创建存储桶
            s3Client.createBucket(bucketName);
            // 设置权限: 公有读
//            s3Client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            // BucketPolicy 授权策略
            // {"Statement": [{"Action": ["s3:GetBucketLocation", "s3:ListBucket"], "Effect": "Allow", "Principal": "*", "Resource": "arn:aws:s3:::%s"}, {"Action": "s3:GetObject", "Effect": "Allow", "Principal": "*", "Resource": "arn:aws:s3:::%s/myobject*"}], "Version": "2012-10-17"}
            // 设置权限: 公有读
            s3Client.setBucketPolicy(bucketName, String.format("{\"Version\": \"2012-10-17\", \"Statement\": [{\"Action\": \"s3:GetObject\", \"Effect\": \"Allow\", \"Principal\": \"*\", \"Resource\": \"arn:aws:s3:::%s/*\"}]}"
                    , bucketName
            ));
        }
        log.info("minio 存储桶 【{}】 创建成功", bucketName);
        return s3Client;
    }

}
